package com.hzya.frame.utils.core.dao;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import javax.annotation.Resource;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import com.hzya.frame.utils.core.entity.BaseEntity;
import com.hzya.frame.utils.core.page.PageHelper;
import com.hzya.frame.utils.core.page.PageInfo;
import com.hzya.frame.utils.help.UtilHelper;

public abstract class MybatisGenericDao<E extends Serializable, PK extends Serializable> implements IBaseDao<E, PK> {
	public static final String POSTFIX_INSERT = "_insert";
	public static final String POSTFIX_UPDATE = "_update";
	public static final String POSTFIX_UPDATE_SELECTIVE = "_updateSelective";
	public static final String POSTFIX_LOGIC_DELETE = "_logicDelete";
	public static final String POSTFIX_LOGIC_DELETE_LOGICDELETE_MULTI_CONDITION = "_logicDelete_Multi_Condition";
	public static final String POSTFIX_DELETE = "_delete";
	public static final String POSTFIX_DELETE_MULTI_CONDITION = "_delete_Multi_Condition";
	public static final String POSTFIX_DELETE_BYKEY = "_deleteByPrimaryKey";
	public static final String POSTFIX_GET = "_get";
	public static final String POSTFIX_SELECT = "_list";
	public static final String POSTFIX_COUNT = "_count";
	public static final String POSTFIX_CUSTOM1 = "_custom1";
	public static final String POSTFIX_CUSTOM2 = "_custom2";
	public static final String POSTFIX_CUSTOM3 = "_custom3";
	private static final Log LOG = LogFactory.getLog(MybatisGenericDao.class);

	@Autowired
	@Resource
	private SqlSession sqlSession;
	private Class<?> entityClass;

	public SqlSession getSqlSession() {
		return this.sqlSession;
	}

	public MybatisGenericDao() {
		Class<?> c = super.getClass();
		Type t = c.getGenericSuperclass();
		if (t instanceof ParameterizedType) {
			this.entityClass = ((Class<?>) ((ParameterizedType) t).getActualTypeArguments()[0]);

			LOG.info("enityClass : " + this.entityClass.toString());
		}
	}

	private String getSqlIdPrifx() {
		String className = this.entityClass.getSimpleName();
		String packAge = this.entityClass.getPackage().getName();
		return packAge + "." + className + "." + className;
	}

	public Object selectOne(String id, Object param) {
		return this.sqlSession.selectOne(id, param);
	}

	public List<?> selectList(String id, Object param) {
		return this.sqlSession.selectList(id, param);
	}

	public List<E> queryByLike(E o) {
		List<E> tempList = this.sqlSession.selectList(getSqlIdPrifx() + "_list_like", o);
		return tempList;
	}

	public List<E> queryByOr(E o) {
		List<E> tempList = this.sqlSession.selectList(getSqlIdPrifx() + "_list_or", o);
		return tempList;
	}

	public E get(PK id) {
		Assert.notNull(id,"get: ID不能为null");
		Object o = this.sqlSession.selectOne(getSqlIdPrifx() + "_get", id);
		return (E) ((Serializable) o);
	}

	public E query(E o, String stamentID) {
		return (E) ((Serializable) this.sqlSession.selectOne(stamentID, o));
	}

	public List<E> queryList(E o, String stamentID) {
		List<E> tempList = this.sqlSession.selectList(stamentID, o);
		return tempList;
	}

	public List<E> getAll() {
		List tempList = this.sqlSession.selectList(getSqlIdPrifx() + "_list_base");
		return tempList;
	}

	public List<E> query(Serializable param) {
		String str=getSqlIdPrifx() + "_list_base";
		List<E> tempList = this.sqlSession.selectList(str, param);
		return tempList;
	}
	public E selectOne(Serializable param) {
		String str=getSqlIdPrifx() + "_list_base";
		E e = this.sqlSession.selectOne(str, param);
		return e;
	}

	public E saveOrUpdate(E o) {
		Assert.notNull(o,"saveOrUpdate : 参数列表不能为NULL");
		Object id = null;
		try {
			id = BeanUtils.getProperty(o, "id");
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}

		if ((id == null) || ("".equals(String.valueOf(id))))
			this.sqlSession.insert(getSqlIdPrifx() + "_insert", o);
		else {
			this.sqlSession.update(getSqlIdPrifx() + "_update", o);
		}

		return o;
	}

	public E queryOne(E o) {
		E e = selectOne(o);
		return e;
	}

	public E update(E o) {
		Assert.notNull(o,"update : 参数列表不能为NULL");
		this.sqlSession.update(getSqlIdPrifx() + "_update", o);
		return o;
	}

	public E save(E o) {
		Assert.notNull(o,"save : 参数列表不能为NULL");
		this.sqlSession.insert(getSqlIdPrifx() + "_insert", o);
		return o;
	}
	public E save(String id, E param) {
        this.sqlSession.insert(id, param);
        return param;
    }
	public int logicRemove(PK id) {
		Assert.notNull(id,"logicRemove : 参数列表不能为NULL");
		return this.sqlSession.update(getSqlIdPrifx() + "_logicDelete", id);
	}
 	public int logicRemoveMultiCondition(E o) {
		Assert.notNull(o,"logicRemoveMultiCondition : 参数列表不能为NULL");
		return this.sqlSession.update(getSqlIdPrifx() + "_logicDelete_Multi_Condition", o);
	} 
	
	public int removeById(PK id) {
		Assert.notNull(id,"removeById : 参数列表不能为NULL");
		int result = this.sqlSession.delete(getSqlIdPrifx() + "_delete", id);

		return result;
	}

	public int remove(String id, Object param) {
		return this.sqlSession.update(id, param);
	}

	public int delete(String id, Object param) {
		return this.sqlSession.delete(id, param);
	}
	
	public int update(String id, Object param) {
		return this.sqlSession.update(id, param);
	}

	public PageInfo<E> queryPaged(Object baseEntity) {
		String sqlId = getSqlIdPrifx() + "_list_like";
		return queryPaged(sqlId, baseEntity);
	}
	/**
	 * 分页查询
	 */
    public PageInfo<E> queryPaged(String statement, Object baseEntity) {
        Assert.notNull(statement,"queryPaged ID 不能为NULL");
        Assert.notNull(baseEntity,"queryPaged baseEntity :参数列表不能为NULL");
        BaseEntity realEntity = (BaseEntity)baseEntity;
        Long rowsParam = realEntity.getRows();
        Long pageParam = realEntity.getPage();
        Long limitParam = realEntity.getLimit();
        Long offsetParam = realEntity.getOffset();
        int page = 1;
        int rows = 10;

        try {
            if(rowsParam != null) {
                rows = rowsParam.intValue();
            } else if(limitParam != null) {
                rows = limitParam.intValue();
            }

            if(pageParam != null) {
                page = pageParam.intValue();
            } else if(offsetParam != null) {
                page = offsetParam.intValue() / rows + 1;
            }
        } catch (Exception var12) {
            var12.printStackTrace();
        }

        PageHelper.startPage(page, rows);
        List<E> list = this.query(statement, baseEntity);
        PageInfo pageInfo = new PageInfo(list);
        return pageInfo;
    }

	public List<E> query(String statement, Object baseEntity) {
		Assert.notNull(statement,"query :ID 不能为NULL");
		Assert.notNull(baseEntity,"query baseEntity :不能为NULL");
		List<E> list=this.sqlSession.selectList(statement, baseEntity);
		return list;
	}

	public Integer getCount(Object parameterObject) {
		Integer totalCount = (Integer) this.sqlSession.selectOne(getSqlIdPrifx() + "_count", parameterObject);

		return totalCount;
	}

	public int delete(PK id) {
		return this.sqlSession.delete(getSqlIdPrifx() + "_delete", id);
	}

	public boolean checkRepeated(E o) {
		Class TargetClass;
		try {
			TargetClass = o.getClass();
			List fieldList = UtilHelper.getPrimaryNameList(TargetClass);
			String id = BeanUtils.getProperty(o, "id");
			boolean flag = true;
			if (fieldList == null)
				return false;

			Object param = org.springframework.beans.BeanUtils.instantiate(TargetClass);
			for (int i = 0; i < fieldList.size(); ++i) {
				Field field = (Field) fieldList.get(i);
				String name = field.getName();
				Object tempVal = BeanUtils.getProperty(o, name);
				if ((tempVal != null) && (!("".equals(tempVal)))) {
					flag = false;
					BeanUtils.setProperty(param, name, BeanUtils.getProperty(o, name));
				}

			}

			if (flag)
				return false;

			List resultList = query((Serializable) param);
			if ((resultList != null) && (resultList.size() > 0)) {
				if ((id == null) || ("".equals(id)))
					return true;

				Object tempResult = resultList.get(0);
				String tempId = BeanUtils.getProperty(tempResult, "id");

				return (!(tempId.equals(id)));
			}

			return false;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
}